function delAttachment(attId, fieldName, flowId, docId, formName, isObjStoreEnabled, pageType, visualPath, diskName, macroType, isFlow, isUseBreakpointResume) {
  // 如果是智能模块的添加页面
  if (pageType == 'add') {
    if (fieldName != null) {
      $(fo('helper_' + fieldName)).html('');
      $(fo('helper_' + fieldName)).hide();
    }

    if (isObjStoreEnabled || isUseBreakpointResume) {
      $('#' + formName + '_' + fieldName).show();
      initAttachmentCtl(formName, fieldName, isUseBreakpointResume);
      // 清除悬浮栏中的节点
      deleteByField(fieldName, visualPath + '/' + diskName);

      // 清空文件宏控件的值，否则仍会显示文件名
      fo(fieldName, formName).value = '';
    }

    return;
  }

  var ajaxData;
  if (macroType == 'macro_image') {
    // 如果图片创建于流程
    if (isFlow) {
      ajaxData = {
        "flowId": flowId,
        "attachId": attId,
        "isFlow": isFlow
      }
    } else {
      ajaxData = {
        "attachId": attId,
        "isFlow": isFlow
      }
    }
  } else {
    if (pageType == 'flow') {
      ajaxData = {
        "flowId": flowId,
        "docId": docId,
        "attachId": attId,
        "isFlow": isFlow
      }
    } else {
      ajaxData = {
        "flowId": flowId,
        "attachId": attId,
        "isFlow": isFlow
      }
    }
  }

	ajaxPost('/flow/delAttach', ajaxData).then((data) => {
		console.log('data', data);
		console.log('isUseBreakpointResume', isUseBreakpointResume);
		myMsg(data.msg);
		if (data.code == 200) {
			if (fieldName != null) {
        if ($(fo(fieldName)).attr('type') == 'file') {
          // 如果不用inline而用show()，会使用文件框的高度变高
          $(fo(fieldName)).css('display', 'inline');
        }

				$(fo('helper_' + fieldName)).html('');
        $(fo('helper_' + fieldName)).hide();

        // 先映射，后上传，然后再删除时，需置映射的值为空，否则后端仍会保存映射的值，并且验证必填也因为有该值而不生效
        $(fo(fieldName + '_mapped')).val('');
        if (macroType == 'macro_image') {
          $(fo(fieldName + 'Img')).html('');
        }
			}

      // 文件被删除事件
      eventTarget.fireEvent({
        type: EVENT_TYPE.ATTACHMENT_DELETED,
        params: ajaxData,
      });    
      
			// 刷新附件列表
			reloadAttachment();

      if (isObjStoreEnabled || isUseBreakpointResume) {
        $('#' + formName + '_' + fieldName).show();
        fo(fieldName).value = '';

        initAttachmentCtl(formName, fieldName, isUseBreakpointResume);
        // 清除悬浮栏中的节点
        deleteByField(fieldName);
      }
		}
	});
}

// 当文件上传后即隐藏上传文件链接，防止网卡时，用户仍可以点击上传，导致前后上传的文件名交替闪现
function hideUploadLink(formName, fieldName) {
  $('#' + formName + '_' + fieldName).hide();
  console.log(fieldName + ' upload link is hided');
}

function delAtt(attId, fieldName, flowId, docId, formName, isObjStoreEnabled, pageType, visualPath, diskName, macroType, isFlow, isUseBreakpointResume) {
	myConfirm('提示', '您确定要删除么', function() { delAttachment(attId, fieldName, flowId, docId, formName, isObjStoreEnabled, pageType, visualPath, diskName, macroType, isFlow, isUseBreakpointResume) });
}

function showUploadLink(formName, fieldName, isShow) {
  if (isShow) {
    $('#' + formName + '_' + fieldName).show();
  } else {
    $('#' + formName + '_' + fieldName).hide();
  }
}

// 置上传进度
function putUploadProgress(data) {
  console.log('putUploadProgress', data);
  console.log("$('.barbox').width", $('.barline').width());
  var formName = data.formName;
  var objForm = o(formName);
  var progress = data.progress;
  var fileName = data.fileName;
  var fieldTitle = data.fieldTitle;

  // 隐藏上传文件链接
  showUploadLink(formName, data.fieldName, false);

  $(objForm).find('#barlineBar_' + formName + '_' + data.fieldName).width(data.progress*($('.barline').width()/100) + 'px');
  $(objForm).find('#barPercent_' + data.fieldName).html(data.progress + '%');

  var fileNameHtml = data.fileName;
  if (progress > 0 || progress != undefined) {
    // 上传没结束时不允许出现删除按钮，因为浏览器还会继续上传
    // fileNameHtml += '<span class="barline-remove" onclick="removeUploadFile(&quot;' + data.formName + '&quot;, &quot;' + data.fieldName + '&quot;)">×</span>';
  }
  $(objForm).find('#barFileName_' + formName + '_' + data.fieldName).html(fileNameHtml);
  if (data.progress == 100) {
    if (data.isUseBreakpointResume && !data.isMerged) {
      return;
    }

    var diskName = data.fieldValue;
    var p = diskName.lastIndexOf('/');
    if (p!=-1) {
      // obs中需去掉fileName中与filePath重复的部分
      diskName = diskName.substring(p + 1);
    }

    var pageType = data.pageType;
    var params = {
      fieldName: data.fieldName,
      formCode: data.formCode,
      pageType: pageType,
      mainId: data.mainId,
      fileName: fileName,
      fileSize: data.file.size,
      diskName: diskName,
      filePath: data.filePath,
      macroType: data.macroType,
      file: data.file,
      myActionId: data.myActionId,
    }
    console.log('finishUpload params', params);
    // 在嵌套表格中上传时，pageType原为空，所以此处需加以判断并赋值
    if (data.fieldName.indexOf('nest_field_')==0) {
      params.pageType = 'add_relate';
    }
    ajaxPost('/flow/macro/finishUpload', params).then((res) => {
        console.log('res', res);
        if (res.code==200) {
            myMsg(fieldTitle + ": " + fileName + ' 上传成功');
            // 如果是智能模块的添加页面
            if (pageType == 'add' || pageType == 'add_relate') {
              // 如果fieldName不为att开头，则说明是文件宏控件所传，在隐藏表单域中写入diskName
              console.log('diskName', diskName, 'formName', data.formName, 'fieldName', data.fieldName);
              if (data.fieldName.indexOf('att') != 0) {
                fo(data.fieldName, data.formName).value = diskName;
              } else {
                // 通过上传文件按钮上传，则加入隐藏表单域
                $(o(formName)).append('<input name="att" value="' + diskName + '" type="hidden" />');
              }
            } else if (pageType == 'noticeAdd') {
              addTempAtt(res.data.id);
            }

            params.isEditable = true;
            params.canDel = true;
            params.attId = res.data.id;
            params.attName = data.fileName;
            params.visitKey = res.data.visitKey;
            params.formName = data.formName;

            params.canPreview = res.data.canPreview;
            params.previewUrl = res.data.previewUrl;
            params.visualPath = params.filePath;

            console.log('getServerInfo()', getServerInfo());
            params.isObjStoreEnabled = getServerInfo().isObjStoreEnabled;
            params.isUseBreakpointResume = getServerInfo().isUseBreakpointResume;
            params.rootPath = getServerInfo().rootPath;

            params.macroType = data.macroType;

            // 置fileTreeList信息，以便于“上传按钮”显示预览按钮
            setUploadFileTreeListAttInfo(data.file, params.attId, params.canPreview, params.previewUrl, params.visitKey, diskName);

            // 刷新附件列表
            console.log('putUploadProgress pageType', pageType);
            if (pageType === 'flow') {
              reloadAttachment();
              params.isFlow = true;
            }
            else if (pageType === 'edit' || data.pageType === 'edit_relate') {
              // else if (pageType === 'edit' && data.fieldName != 'att') {
              reloadAttachment();
            } else if (pageType == 'noticeEdit') {
              reloadAttachment();
            }

            // 如果不是通过上传按钮上传文件，则渲染文件宏控件
            if (data.fieldName.indexOf('att') != 0) {
              displayAttachment(params);

              // 上传文件完成事件
              eventTarget.fireEvent({
                type: EVENT_TYPE.ATTACHMENT_UPLOADED,
                params: params,
              });              
            }
        } else {
            myMsg(res.msg, 'error');
        }
    });
  }
}

// 清除
// function removeUploadFile(formName, fieldName) {
//   $('#barBox_' + formName + '_' + fieldName).remove();
//   initAttachmentCtl(formName, fieldName);
// }

function initAttachmentCtl(formName, fieldName, isUseBreakpointResume) {
  console.log('formName', formName, 'fieldName', fieldName);
  if (!o(formName))
    return;

  $('#barBox_' + formName + '_' + fieldName).remove();

  let str = '';
  str += "<div id=\"barBox_" + formName + '_' + fieldName + "\" class=\"barbox\">";
  str += "<div id=\"barFileName_" + formName + '_' + fieldName + "\" class=\"barline-filename\"></div>";
  str += "<div class=\"barline\" id=\"proBar_" + formName + '_' + fieldName + "\">";
  str += "	<div id=\"barlineBar_" + formName + '_' + fieldName + "\" class=\"barline-bar\" style=\"width:0px;\"></div>";
  str += "</div>";
  if (isUseBreakpointResume) {
    str += "<div id=\"barBtn_" + formName + "_" + fieldName + "_cancel\" class=\"barline-btn-cancel\" onclick=\"doCancel('" + formName + "', '" + fieldName + "');showUploadLink('" + formName + "','" + fieldName + "',true);initAttachmentCtl('" + formName + "','" + fieldName + "'," + isUseBreakpointResume + ")\" title=\"取消\">×</div>"; 
    str += "<div id=\"barBtn_" + formName + "_" + fieldName + "_pause\" class=\"barline-btn-pause\" onclick=\"doPause('" + formName + "', '" + fieldName + "')\" title=\"暂停\">▌▌</div>";
    str += "<div id=\"barBtn_" + formName + "_" + fieldName + "_start\" class=\"barline-btn-start\" onclick=\"doStart('" + formName + "', '" + fieldName + "')\" title=\"继续\">4</div>"; 
  }
  str += "<div id=\"barPercent_" + fieldName + "\" class=\"barline-percent\"></div>";
  str += "</div>"; 
  $('#' + formName + '_' + fieldName).after(str);
  return str;
}

// 显示已上传的文件及预览
function displayAttachment(json) {
  console.log('displayAttachment json', json);
  var isObjStoreEnabled = json.isObjStoreEnabled;
  var isUseBreakpointResume = json.isUseBreakpointResume;
  var formName = json.formName;
  var fieldName = json.fieldName;
  var attId = json.attId;
  var attName = json.attName;
  var isEditable = json.isEditable;
  var visualPath = json.visualPath;
  var diskName = json.diskName;
  var pageType = json.pageType;
  var canDel = json.canDel;
  var visitKey = json.visitKey;
  var rootPath = json.rootPath;
  var mainId = json.mainId; // flowId或模块记录的id
  var isFlow = json.isFlow; // 是否流程
  var canPreview = json.canPreview;
  var previewUrl = json.previewUrl;
  var macroType = json.macroType;
  var isImg = isImage(diskName);

  console.log('displayAttachment isObjStoreEnabled', isObjStoreEnabled);
  var str = '';
  if (pageType.toLowerCase().indexOf("show") == -1) {
    if (macroType != 'macro_image') {
      if (isObjStoreEnabled) {
        // 去掉末尾的 /，兼容2019旧版
        if (visualPath.slice(-1) == '/') {
          visualPath = visualPath.slice(0, -1);
        }
        str += "<a href='javascript:;' onclick=\"downloadObsFile('" + visualPath + '/' + diskName + "', '" + attName + "')\">" + attName + "</a>";
      } else {
        if (isFlow) {
          str += "<a href='javascript:;' onclick=\"downloadFile('" + attName + "', {attachId:" + attId + ", flowId:" + mainId + "})\">" + attName + "</a>";
        }
        else {
          str += "<a href='javascript:;' onclick=\"downloadFileVisual('" + attName + "', {attachId:" + attId + ", visitKey:'" + visitKey + "'})\">" + attName + "</a>";
        }
      }

      // if (isImg) {
      //   str += "&nbsp;&nbsp;<a href='javascript:;' onclick=\"window.open('" + rootPath +"/showImg.do?visitKey=" + visitKey + "&path="+ visualPath + "/" + diskName + "')\">查看</a>";      
      // }
      
      if (canPreview) {
        if (previewUrl.indexOf('window.') == -1)
          str += "&nbsp;&nbsp;<a href='javascript:;' onclick=\"window.open('" + previewUrl + "')\">预览</a>"
        else
          str += "&nbsp;&nbsp;" + previewUrl;
      }
    }

    // 如果是可编辑状态
    if (isEditable) {
      // 如果是图像宏控件，则显示所选的图片
      if (macroType == 'macro_image') {
        const curFile = json.file;
        console.log('curFile', curFile);
        if (curFile) {
          const reader = new FileReader();
          reader.readAsDataURL(curFile);
          reader.onload = function () {
            const w = $(fo(fieldName)).attr('w');
            const h = $(fo(fieldName)).attr('h');
            let style = '';
            if (w && h) {
              style = 'width: ' + w + 'px; height:' + h + 'px';
            } else if (w) {
              style = 'width: ' + w;
            }
  
            $(fo(fieldName + 'Img')).html('<img src="' + reader.result + '" style="' + style + '"/>');
          };
        }
      }

      // 如果文件宏控件是在流程处理界面上，而只有一个元素，说明是映射过来的，不能删除
      if (macroType == 'macro_image' || canDel) {
          if (macroType == 'macro_image') {
            str += '<span style="float:right">';
          }
          str += "&nbsp;&nbsp;<a href='javascript:;' class='btn-att-remove' title='删除' onclick=\"delAtt(" + attId + ", '" + fieldName + "', " + mainId + ", null, '" + formName + "', " + isObjStoreEnabled + ", '" + pageType + "','" + visualPath + "','" + diskName + "', '" + macroType + "', " + isFlow + ", " + isUseBreakpointResume + ")\">×</a>";
          if (macroType == 'macro_image') {
            str += '</span>';
          }
      } else {
        setTimeout(()=>{
          console.log('displayAttachment now show ' + formName + '_' + fieldName);
          // 如果是映射过来的，则使“上传文件”链接出现，以便于能够替换原来映射的文件
          $('#' + formName + '_' + fieldName).show();
        }, 2000);
      }

      // 当删除原来已上传的文件，重新再上传时，需置该元素为input hidden的值，否则在提交后，保存的仍是原来的值
      var fieldVal = '';
      if (pageType == 'flow') {
        fieldVal = mainId + ',' + attId;
      } else {
        fieldVal = diskName;
      }
      console.log('displayAttachment fo(fieldName)', fo(fieldName));
      if (fo(fieldName).type != 'file') {
        fo(fieldName).value = fieldVal;
      }
    }
  } else {
    if (macroType != 'macro_image') {
      if (false && isImg) {
          str += "<a href='javascript:;' onclick=\"window.open('" + rootPath +"/showImg.do?visitKey=" + visitKey + "&path="+ visualPath + "/" + diskName + "')\">" + attName + "</a>";
      } else {
        if (isObjStoreEnabled) {
          str += "<a href='javascript:;' onclick=\"downloadObsFile('" + visualPath + '/' + diskName + "', '" + attName + "')\">" + attName + "</a>";
        } else {
          if (isFlow) {
            str += "<a href='javascript:;' onclick=\"downloadFile('" + attName + "', {attachId:" + attId + ", flowId:" + mainId + "})\">" + attName + "</a>";
          }
          else {
            str += "<a href='javascript:;' onclick=\"downloadFileVisual('" + attName + "', {attachId:" + attId + ", visitKey:'" + visitKey + "'})\">" + attName + "</a>";
          }
        }
      }

      if (canPreview) {
        if (previewUrl.indexOf('window.') == -1)
          str += "&nbsp;&nbsp;<a href='javascript:;' onclick=\"window.open('" + previewUrl + "')\">预览</a>"
        else
          str += "&nbsp;&nbsp;" + previewUrl;
      }
    }
  }

  console.log('displayAttachment str', str);

  $('#helper_' + fieldName).html(str);
  $('#helper_' + fieldName).show();
  if (macroType == 'macro_image') {
    var imgWidth = $(fo(fieldName)).attr('w');
    if (imgWidth) {
      $('#helper_' + fieldName).width(imgWidth);
    }
  }

  // 隐藏上传文件链接
  $('#' + formName + '_' + fieldName).hide();
  // 隐藏进度条
  $('#barFileName_' + formName + '_' + fieldName).hide();
  // $('#barBox_' + formName + '_' + fieldName).remove();
}